﻿using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.Runtime.Serialization;
using System.Windows.Forms;

namespace CartoGraphic.Model2
{
    public class Polygon : LineObj
    {
        private ArrayList pointArray; // list of points
        private Cursor handleCursor;

        private const string entryLength = "Length";
        private const string entryPoint = "Point";
        private double area;


        public Polygon()
        {
            pointArray = new ArrayList();

            LoadCursor();
            Initialize();
        }

        public Polygon(int x1, int y1, int x2, int y2)
        {
            pointArray = new ArrayList();
            pointArray.Add(new Point(x1, y1));
            pointArray.Add(new Point(x2, y2));
            Filled = true;
            LoadCursor();
            Initialize();
        }

        public double Area
        {
            get { return area; }
            set { area = value; }
        }



        public ArrayList PointArray
        {
            get { return pointArray; }
            set { pointArray = value; }
        }

        //public int CompareTo(object right)
        //{
        //    if (!(right is Polygon))
        //    {
        //        throw new ArgumentException("");
        //    }
        //    if (this.Area < (right as Polygon).Area)
        //        return 1;
        //    else
        //        return 0;
        //}


        //public Polygon(int x1, int y1, int x2, int y2, DrawingPens.PenType p,FillBrushes.BrushType b)
        //{
        //    pointArray = new ArrayList();
        //    pointArray.Add(new Point(x1, y1));
        //    pointArray.Add(new Point(x2, y2));
        //    //DrawPen = DrawingPens.SetCurrentPen(p);
        //    //DrawBrush = FillBrushes.SetCurrentBrush(b);
        //    PenType = p;
        //    LoadCursor();
        //    Initialize();
        //}

        public Polygon(int x1, int y1, int x2, int y2, Color lineColor, int lineWidth)
        {
            pointArray = new ArrayList();
            pointArray.Add(new Point(x1, y1));
            pointArray.Add(new Point(x2, y2));
            Color = lineColor;
            PenWidth = lineWidth;

            LoadCursor();
            Initialize();
        }

        public override BaseDrawingObj Clone()
        {
            Polygon drawPolygon = new Polygon();

            foreach (Point p in pointArray)
            {
                drawPolygon.pointArray.Add(p);
            }

            FillDrawObjectFields(drawPolygon);
            return drawPolygon;
        }

        public override void Draw(Graphics g, GraphicsProperties gps)
        {
            Pen pen = new Pen(gps.BorderColor, gps.PenWidth);
            Brush b = new SolidBrush(gps.FillColor);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            Point[] pts = new Point[pointArray.Count];
            for (int i = 0; i < pointArray.Count; i++)
            {
                Point px = (Point)pointArray[i];
                pts[i] = px;
            }
            byte[] types = new byte[pointArray.Count];
            for (int i = 0; i < pointArray.Count; i++)
                types[i] = (byte)PathPointType.Line;
            GraphicsPath gp = new GraphicsPath(pts, types);
            
            if (gps.Fill)
                g.FillPath(b, gp);
            g.DrawPath(pen, gp);
            g.DrawLine(pen, pts[0], pts[pts.Length - 1]);
            gp.Dispose();
            b.Dispose();
            pen.Dispose();
        }

        public void AddPoint(Point point)
        {
            pointArray.Add(point);
        }

        public override int HandleCount
        {
            get { return pointArray.Count; }
        }

        public override Point GetHandle(int handleNumber)
        {
            if (handleNumber < 1)
                handleNumber = 1;

            if (handleNumber > pointArray.Count)
                handleNumber = pointArray.Count;

            return ((Point)pointArray[handleNumber - 1]);
        }

        public override Cursor GetHandleCursor(int handleNumber)
        {
            return handleCursor;
        }

        public override void MoveHandleTo(Point point, int handleNumber)
        {
            if (handleNumber < 1)
                handleNumber = 1;

            if (handleNumber > pointArray.Count)
                handleNumber = pointArray.Count;

            pointArray[handleNumber - 1] = point;
            Dirty = true;
            Invalidate();
        }

        public override void Move(int deltaX, int deltaY)
        {
            int n = pointArray.Count;

            for (int i = 0; i < n; i++)
            {
                Point point;
                point = new Point(((Point)pointArray[i]).X + deltaX, ((Point)pointArray[i]).Y + deltaY);

                pointArray[i] = point;
            }
            Dirty = true;
            Invalidate();
        }

        public override void SaveToStream(SerializationInfo info, int orderNumber, int objectIndex)
        {

        }

        public override void LoadFromStream(SerializationInfo info, int orderNumber, int objectIndex)
        {

        }

        protected override void CreateObjects()
        {
            if (AreaPath != null)
                return;
            AreaPath = new GraphicsPath();

            int x1 = 0, y1 = 0; // previous point

            IEnumerator enumerator = pointArray.GetEnumerator();

            if (enumerator.MoveNext())
            {
                x1 = ((Point)enumerator.Current).X;
                y1 = ((Point)enumerator.Current).Y;
            }

            while (enumerator.MoveNext())
            {
                int x2, y2; // current point
                x2 = ((Point)enumerator.Current).X;
                y2 = ((Point)enumerator.Current).Y;

                AreaPath.AddLine(x1, y1, x2, y2);

                x1 = x2;
                y1 = y2;
            }

            AreaPath.CloseFigure();

            // Create region from the path
            AreaRegion = new Region(AreaPath);
        }

        private void LoadCursor()
        {
            handleCursor = Cursors.Default;
        }
    }
}
